<!DOCTYPE html>
<html lang="en">
    <head>
  <!-- 元数据 -->
  <meta charset="utf-8">
  <link rel="icon" href="https://gitee.com/cuishikang/tmp/raw/master/img/boke.png">
  <title>3. Vue移动端 基本登录功能 | 小崔的博客</title>
  <meta name="author" content="cuishikang" />
  <meta http-equiv="Cache-Control" content="no-transform" />
  <meta http-equiv="Cache-Control" content="no-siteapp" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="robots" content="index,follow" />
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
  <meta name="format-detection" content="telphone=no, email=no" />
  
    <meta name="keywords" content="Vant, Vue, Vue移动端" />
  
  <meta name="description" content="::: tip 介绍 Vant插件的登录功能(基本功能 访问数据 访问权限功能 token续签):::">
<meta property="og:type" content="article">
<meta property="og:title" content="3. Vue移动端 基本登录功能">
<meta property="og:url" content="https://cuishikang.gitee.io/2021/06/04/Vue_Mobile_Projects/4_login/index.html">
<meta property="og:site_name" content="小崔的博客">
<meta property="og:description" content="::: tip 介绍 Vant插件的登录功能(基本功能 访问数据 访问权限功能 token续签):::">
<meta property="og:locale" content="en_US">
<meta property="og:image" content="https://gitee.com/cuishikang/tmp/raw/master/img/boke.png">
<meta property="article:published_time" content="2021-06-03T16:00:00.000Z">
<meta property="article:modified_time" content="2022-02-19T10:22:58.545Z">
<meta property="article:author" content="cuishikang">
<meta property="article:tag" content="Vue">
<meta property="article:tag" content="Vue移动端">
<meta property="article:tag" content="Vant">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://gitee.com/cuishikang/tmp/raw/master/img/boke.png">
<meta name="twitter:site" content="@null">
  
  <!-- 站点验证相关 -->
  
    
    
    
  
  <!-- 样式表文件 -->
  <link rel="stylesheet" id="kratos-css" href="/css/kratosr.min.css" type="text/css" media="all">
  
    <link rel="stylesheet" id="highlight-css" href="/css/highlight/night-eighties.min.css" type="text/css" media="all">
  
  
  <link rel="stylesheet" id="fontawe-css" href="https://unpkg.com/font-awesome@4.7.0/css/font-awesome.min.css" type="text/css" media="all">
  <link rel="stylesheet" id="nprogress-css" href="https://unpkg.com/nprogress@0.2.0/nprogress.css" type="text/css" media="all">
  
  
    <link rel="stylesheet" href="https://unpkg.com/aplayer@1.10.1/dist/APlayer.min.css">
  
  
    <link rel="stylesheet" href="https://unpkg.com/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css">
  
  
    <link rel="stylesheet" id="darkmode-css" href="/css/kr-dark.min.css" type="text/css" media="all">
  
  <!-- 不得不预先加载的一些JS文件 -->
  <script src="https://unpkg.com/jquery@3.6.0/dist/jquery.min.js"></script>
  
    <script src="https://unpkg.com/qrcode_js@1.0.0/qrcode.min.js"></script>
  
  
  <style>
    
      .kratos-cover.kratos-cover-2 {
        background-image: url('/images/banner.webp');
      }
    
    
      @media(min-width:768px) {
        body.custom-background {
          background-image: url('/images/bg.webp');
        }
      }
    
  </style>
  
<meta name="generator" content="Hexo 6.0.0"></head>


    <body class="custom-background">
        <div id="kratos-wrapper">
    <div id="kratos-page">
        <div id="kratos-header">
            <header id="kratos-desktop-topnav" class="kratos-topnav">
                <div class="container">
                    <div class="nav-header">
                        <nav id="kratos-menu-wrap">
                            <ul id="kratos-primary-menu" class="sf-menu">
                                
                                    
                                        <li><a href="/"><i class="fa fa-home"></i>首页</a></li>
                                    
                                
                                    
                                        <li><a href="/archives/"><i class="fa fa-file"></i>档案馆</a></li>
                                    
                                
                                    
                                        <li><a href="/friends/"><i class="fa fa-paw"></i>好伙伴</a></li>
                                    
                                
                                    
                                        <li>
                                            <a><i class="fa fa-link"></i>关于本人</a>
                                            <ul class="sub-menu">
                                                
                                                    
                                                
                                                    
                                                        <li><a target="_blank" rel="noopener" href="https://gitee.com/cuishikang"><i class="fa fa-git"></i>码云</a></li>
                                                    
                                                
                                                    
                                                        <li><a target="_blank" rel="noopener" href="https://gitee.com/cuishikang/tmp/raw/master/img/2201645358312_.pic.jpg"><i class="fa fa-weixin"></i>微信</a></li>
                                                    
                                                
                                                    
                                                        <li><a target="_blank" rel="noopener" href="https://www.zhihu.com/people/fu-xi-ting-67-17-5"><i class="fa  fa-search"></i>知乎</a></li>
                                                    
                                                
                                                    
                                                        <li><a href="http://cuishikang.gitee.io/my_resume/#/"><i class="fa  fa-file-o"></i>简历</a></li>
                                                    
                                                
                                            </ul>
                                        </li>
                                    
                                
                            </ul>
                        </nav>
                    </div>
                </div>
            </header>
            <header id="kratos-mobile-topnav" class="kratos-topnav">
                <div class="container">
                    <div class="color-logo"><a href="/">小崔的博客</a></div>
                    <div class="nav-toggle">
                        <a class="kratos-nav-toggle js-kratos-nav-toggle">
                            <i></i>
                        </a>
                    </div>
                </div>
            </header>
        </div>
        <div class="kratos-start kratos-hero-2">
            <!-- <div class="kratos-overlay"></div> -->
            <div class="kratos-cover kratos-cover-2 text-center">
                <div class="desc desc2 animate-box">
                    <a href="/">
                        <h2>小崔的博客</h2> <br />
                        <span></span>
                    </a>
                </div>
            </div>
        </div>

        <div id="kratos-blog-post">
            <div class="container">
                <div id="main" class="row">
                    

        

            <section class="col-md-8">

        

            <article>
    <div class="kratos-hentry kratos-post-inner clearfix">
        <header class="kratos-entry-header">
            
                <h1 class="kratos-entry-title text-center">3. Vue移动端 基本登录功能</h1>
            
            
            <ul class="kratos-post-meta text-center">
                <li><i class="fa fa-calendar"></i> 2021-06-04</li>
                <li><i class="fa fa-user"></i> 作者 cuishikang</li>
                <li>
                    <i class="fa fa-edit"></i> 
                    
                    
                        ~21.59K
                    
                    字
                </li>
                
            </ul>
        </header>
        <div class="kratos-post-content">
            <div id="expire-alert" class="alert alert-warning hidden" role="alert">
                本文最后编辑于 <time datetime="1645266178545"></time> 前，其中的内容可能需要更新。
            </div>
            
            <hr />
            <p>::: tip 介绍</p>
<p>Vant插件的登录功能(基本功能 访问数据 访问权限功能 token续签)<br><br>:::</p>
<span id="more"></span>

<h2 id="页面基本布局-Login-vue"><a href="#页面基本布局-Login-vue" class="headerlink" title="页面基本布局 Login.vue"></a>页面基本布局<code> Login.vue</code></h2><blockquote>
<p>目标：实现登录页面基本布局<code> Login.vue</code>设置</p>
</blockquote>
<ul>
<li>进行表单<code>v-model</code>双向绑定 验证数据</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    &lt;!-- 标题 --&gt;</span><br><span class="line">    &lt;van-nav-bar title=&#x27;登录&#x27; /&gt;</span><br><span class="line">    &lt;!-- 表单 --&gt;</span><br><span class="line">    &lt;van-cell-group&gt;</span><br><span class="line">      &lt;van-field v-model=&quot;mobile&quot; label=&quot;手机号&quot; placeholder=&quot;请输入手机号&quot; /&gt;</span><br><span class="line">      &lt;van-field v-model=&quot;code&quot; label=&quot;验证码&quot; placeholder=&quot;请输入验证码&quot;&gt;</span><br><span class="line">        &lt;!-- #button 调用Vant的button具名插槽 里面填充内容 #button 是v-slot 具名插槽的简写 --&gt;</span><br><span class="line">        &lt;!-- size 是控制器大小 --&gt;</span><br><span class="line">        &lt;template #button&gt;</span><br><span class="line">          &lt;van-button class=&quot;p5&quot; slot=&quot;button&quot; size=&quot;small&quot; type=&quot;primary&quot;&gt;发送验证码&lt;/van-button&gt;</span><br><span class="line">        &lt;/template&gt;</span><br><span class="line">      &lt;/van-field&gt;</span><br><span class="line">    &lt;/van-cell-group&gt;</span><br><span class="line">    &lt;!-- 提交按钮 --&gt;</span><br><span class="line">    &lt;div class=&quot;btn&quot;&gt;</span><br><span class="line">      &lt;van-button @click=&quot;getLogin&quot; type=&quot;info&quot; block round&gt;登 录&lt;/van-button&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>总结：基于Vant提供的UI组件实现登录页面基本布局。</p>
</blockquote>
<h2 id="实现基本登录功能-Login-vue"><a href="#实现基本登录功能-Login-vue" class="headerlink" title="实现基本登录功能 Login.vue"></a>实现基本登录功能<code> Login.vue</code></h2><blockquote>
<p>实现登录基本功能分为两步: </p>
</blockquote>
<ol>
<li>在api文件夹创建单独控制登录页面的 js文件 <code> api文件夹 创建 login.js</code></li>
<li>在<code> Login.vue</code>文件里面调入Login登录路由配置 验证登录 </li>
<li><code>native-type=&quot;submit&quot; / button</code> submit提交表单并且可以跳转 button提交表单但会阻止跳转(Vant提供的方法)</li>
</ol>
<h3 id="创建单独控制登录页api-request-js"><a href="#创建单独控制登录页api-request-js" class="headerlink" title="创建单独控制登录页api request.js"></a>创建单独控制登录页api<code> request.js</code></h3><ul>
<li>调用通用的接口模块 <code>utils文件夹 request.js</code></li>
<li>创建命名导出 <code>Login.vue</code>接收js文件</li>
<li>配置登录axios 实现登录验证</li>
<li>需要设置<code>return</code>让数据返回</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// Login业务模块，专门负责调用接口</span></span><br><span class="line"><span class="comment">// 导入配置的axios通用的接口模块</span></span><br><span class="line"><span class="keyword">import</span> request <span class="keyword">from</span> <span class="string">&#x27;../utils/request&#x27;</span></span><br><span class="line"><span class="comment">// 配置登录axios 实现登录验证</span></span><br><span class="line"><span class="comment">// 使用命名导出</span></span><br><span class="line"><span class="comment">// 需要设置形参 获取页面的数据 传给axios组件</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> <span class="title function_">login</span> = (<span class="params">mobile, code</span>) =&gt; &#123;</span><br><span class="line">  <span class="comment">// 返回数据设置 return</span></span><br><span class="line">  <span class="keyword">return</span> <span class="title function_">request</span>(&#123;</span><br><span class="line">    <span class="attr">method</span>: <span class="string">&#x27;POST&#x27;</span>,</span><br><span class="line">    <span class="attr">url</span>: <span class="string">&#x27;v1_0/authorizations&#x27;</span>,</span><br><span class="line">    <span class="attr">data</span>: &#123; <span class="comment">// 跟服务器比对数据</span></span><br><span class="line">      mobile,</span><br><span class="line">      code</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>



<blockquote>
<p>目标：创建单独控制登录页的api 链接通用的接口模块<code>index,js</code> 再导入登录主页 <code> api文件夹 创建 login.js</code></p>
</blockquote>
<ul>
<li>表单数据绑定：v-model双向数据绑定</li>
<li>提交按钮事件绑定：绑定点击事件</li>
<li>调用接口-业务方法封装</li>
<li>用于单独控制登录页面的接口调用</li>
</ul>
<h3 id="登录页面验证登录-Login-vue"><a href="#登录页面验证登录-Login-vue" class="headerlink" title="登录页面验证登录  Login.vue"></a>登录页面验证登录 <code> Login.vue</code></h3><blockquote>
<p>数据绑定 <code>template</code></p>
</blockquote>
<ul>
<li>表单数据绑定：v-model双向数据绑定</li>
<li>提交按钮事件绑定：绑定点击事件</li>
</ul>
<blockquote>
<p>数据验证 <code>script</code></p>
</blockquote>
<ul>
<li>用try{}catch{}语法 验证数据是否正确 catch{}提示用户登录失败<ul>
<li>需要进行输入效验 判断token值是否获取 和 服务器返回值 <code> if (ret.status === 201)</code>和<code>if (ret.data.data.token) </code></li>
</ul>
</li>
<li>如果用户登录成功 需要缓存其token值<code>sessionStorage.setItem(&#39;保存名称&#39;, JSON.stringify(获取的token路径))</code><ul>
<li>axios自带data token在data.data里面<code>sessionStorage.setItem(&#39;mytoken&#39;, JSON.stringify(ret.data.data))</code></li>
</ul>
</li>
<li>如果全局引入 Vant 可以用 <code>this.$toast(&#39;登录失败&#39;)</code>来调用Vant的提示插件</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line">&lt;script&gt;</span><br><span class="line">// 1. 传入 login axios 组件 login是登录验证axios命名方法名称</span><br><span class="line">import &#123; login &#125; from &#x27;../api/login&#x27;</span><br><span class="line">export default &#123;</span><br><span class="line">  // 2. 设置 用户输入数据的储存</span><br><span class="line">  data () &#123;</span><br><span class="line">    return &#123;</span><br><span class="line">      mobile: &#x27;&#x27;,</span><br><span class="line">      code: &#x27;&#x27;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  methods: &#123;</span><br><span class="line">    // 3. 创建数据验证方法</span><br><span class="line">    async getLogin () &#123;</span><br><span class="line">      // 4. 用try catch 来判断 数据是否接收成功 提示用户</span><br><span class="line">      try &#123; // 给服务器发送信息</span><br><span class="line">        // 5. 传入用户输入的数值 login是封装的axios登录验证方法名称</span><br><span class="line">        const ret = await login(this.mobile, this.code)</span><br><span class="line">        // 6. 进行判断 获取数据 如果获取成功 保存后端返回的 token值 不成功提示用户</span><br><span class="line">        if (ret.status === 201) &#123;</span><br><span class="line">          // 7. 再进行判断 如果用户获取到后端的token 再让其登录</span><br><span class="line">          if (ret.data.data.token &amp;&amp; ret.data.data.refresh_token) &#123;</span><br><span class="line">            // 8. 保存token值(服务器缓存)</span><br><span class="line">            // sessionStorage.setItem(&#x27;保存名称&#x27;, JSON.stringify(获取的token路径)); 保存token到服务器缓存</span><br><span class="line">            // JSON.stringif()把获取的token转换成字符串</span><br><span class="line">            sessionStorage.setItem(&#x27;mytoken&#x27;, JSON.stringify(ret.data.data))</span><br><span class="line">            // 9. 登录成功 跳转到主页</span><br><span class="line">            this.$router.push(&#x27;/home&#x27;)</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;</span><br><span class="line">      &#125; catch (error) &#123;</span><br><span class="line">        // 登录失败时候会进入 catch 参数是错误信息</span><br><span class="line">        console.log(error)</span><br><span class="line">        // 10. 提示用户登录失败 $toast是Vant提供的模板</span><br><span class="line">        this.$toast(&#x27;登录失败&#x27;)</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure>

<ul>
<li>跳转路由</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">this</span>.<span class="property">$router</span>.<span class="title function_">push</span>(<span class="string">&#x27;/home&#x27;</span>)</span><br></pre></td></tr></table></figure>

<blockquote>
<p>总结：绑定表单数据；绑定提交事件；调用接口；跳转页面。</p>
</blockquote>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/ApcZa8H4L6sDCxO.png" alt="image-20210602161633614"></p>
<blockquote>
<p>总结：封装的好处</p>
<ol>
<li>降低模块之间的耦合性（联系），方便后续的维护和扩展</li>
<li>代码的逻辑结构比较清晰（单一职责）</li>
</ol>
</blockquote>
<h2 id="表单验证-Login-vue"><a href="#表单验证-Login-vue" class="headerlink" title="表单验证  Login.vue"></a>表单验证 <code> Login.vue</code></h2><blockquote>
<p>目标：能够实现表单验证效果</p>
</blockquote>
<p><a target="_blank" rel="noopener" href="https://vant-contrib.gitee.io/vant/#/zh-CN/field">Vant field输入框样式地址</a></p>
<h3 id="表单验证-手动挡-自己写"><a href="#表单验证-手动挡-自己写" class="headerlink" title="表单验证 手动挡 (自己写)"></a>表单验证 手动挡 (自己写)</h3><blockquote>
<p>template 模板写法</p>
</blockquote>
<ol>
<li><p>绑定错误消息 <code>:error-message=&quot;&quot;</code> </p>
</li>
<li><p>@input是监测输入内容</p>
</li>
</ol>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    &lt;!-- 标题 --&gt;</span><br><span class="line">    &lt;van-nav-bar title=&#x27;登录&#x27; /&gt;</span><br><span class="line">    &lt;!-- 表单 --&gt;</span><br><span class="line">    &lt;van-cell-group&gt;</span><br><span class="line">+      &lt;!-- 调用 Vant方法 @input是监测输入内容 :error-message是提示信息 --&gt;</span><br><span class="line">+      &lt;!-- 给:error-message设置一个 对象储存其数据 进行判断 --&gt;</span><br><span class="line">+      &lt;van-field @input=&#x27;validateMobile&#x27; :error-message=&quot;mobileMsg&quot; v-model=&quot;mobile&quot; label=&quot;手机号&quot; placeholder=&quot;请输入手机号&quot; /&gt;</span><br><span class="line">+      &lt;van-field @input=&quot;validateCode&quot; :error-message=&quot;codeMsg&quot; v-model=&quot;code&quot; label=&quot;验证码&quot; placeholder=&quot;请输入验证码&quot;&gt;</span><br><span class="line">        &lt;!-- #button 调用Vant的button具名插槽 里面填充内容 --&gt;</span><br><span class="line">        &lt;!-- size 是控制器大小 --&gt;</span><br><span class="line">        &lt;template #button&gt;</span><br><span class="line">          &lt;van-button class=&quot;p5&quot; slot=&quot;button&quot; size=&quot;small&quot; type=&quot;primary&quot;&gt;发送验证码&lt;/van-button&gt;</span><br><span class="line">        &lt;/template&gt;</span><br><span class="line">      &lt;/van-field&gt;</span><br><span class="line">    &lt;/van-cell-group&gt;</span><br><span class="line">    &lt;!-- 提交按钮 --&gt;</span><br><span class="line">    &lt;div class=&quot;btn&quot;&gt;</span><br><span class="line">      &lt;van-button :loading=&#x27;isLoading&#x27; native-type=&quot;submit&quot; @click=&quot;getLogin&quot; type=&quot;info&quot; block round&gt;登 录&lt;/van-button&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>script 脚本写法</p>
</blockquote>
<ol>
<li>手机号 验证码 进行单独两项判断 如果输入不正确 赋值给 <code>:error-message=&quot;&quot;</code> 打印错误提示 输入正确 置空<code>:error-message=&quot;&quot;</code> </li>
<li>进行登录按钮效验 如果不满足表单要求 阻止上传到服务器</li>
</ol>
<ul>
<li>验证手机号正则 <code>/^1[34578]\d&#123;9&#125;$/</code> </li>
<li>六位数验证码<code> /^\d&#123;6&#125;$/</code></li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br></pre></td><td class="code"><pre><span class="line">&lt;script&gt;</span><br><span class="line">// 1. 传入 login axios 组件 login是登录验证axios命名方法名称</span><br><span class="line">import &#123; login &#125; from &#x27;../api/login&#x27;</span><br><span class="line">export default &#123;</span><br><span class="line">  // 2. 设置 用户输入数据的储存</span><br><span class="line">  data () &#123;</span><br><span class="line">    return &#123;</span><br><span class="line">      mobile: &#x27;&#x27;,</span><br><span class="line">      code: &#x27;&#x27;,</span><br><span class="line">+      //! 错误提示-手机号</span><br><span class="line">+      mobileMsg: &#x27;&#x27;,</span><br><span class="line">+      //! 错误提示-验证码</span><br><span class="line">+      codeMsg: &#x27;&#x27;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  methods: &#123;</span><br><span class="line">    //! 进行手机号输入验证操作</span><br><span class="line">    validateMobile () &#123;</span><br><span class="line">+      //! 1. 进行手机号格式判断</span><br><span class="line">+      if (!this.mobile) &#123;</span><br><span class="line">+        this.mobileMsg = &#x27;请输入手机号&#x27;</span><br><span class="line">+      &#125; else if (!/^1[34578]\d&#123;9&#125;$/.test(this.mobile)) &#123;</span><br><span class="line">+        this.mobileMsg = &#x27;手机号格式不正确&#x27;</span><br><span class="line">+      &#125; else &#123;</span><br><span class="line">+        //! 2.手机号验证通过 取消提示</span><br><span class="line">+        this.mobileMsg = &#x27;&#x27;</span><br><span class="line">+      &#125;</span><br><span class="line">+    &#125;,</span><br><span class="line">+    validateCode () &#123;</span><br><span class="line">+      //! 3. 进行验证码格式判断(六位数验证码)</span><br><span class="line">+      if (!this.code) &#123;</span><br><span class="line">+        this.codeMsg = &#x27;请输入验证码&#x27;</span><br><span class="line">+      &#125; else if (!/^\d&#123;6&#125;$/.test(this.code)) &#123;</span><br><span class="line">+        this.codeMsg = &#x27;验证码格式不正确&#x27;</span><br><span class="line">+      &#125; else &#123;</span><br><span class="line">+        //! 4. 验证通过 取消提示</span><br><span class="line">+        this.codeMsg = &#x27;&#x27;</span><br><span class="line">+      &#125;</span><br><span class="line">+    &#125;,</span><br><span class="line">    // 3. 创建数据验证方法</span><br><span class="line">    async getLogin () &#123;</span><br><span class="line">      // 4. 用try catch 来判断 数据是否接收成功 提示用户</span><br><span class="line">      try &#123; // 给服务器发送信息</span><br><span class="line">+        //! 5. 调用登录效验方法</span><br><span class="line">+        this.validateMobile()</span><br><span class="line">+       this.validateCode()</span><br><span class="line">+        //! 6. 通过提示信息判断是否效验成功 不成功 提示用户失败 跳出判断</span><br><span class="line">+        if (this.mobileMsg !== &#x27;&#x27; || this.codeMsg !== &#x27;&#x27;) &#123;</span><br><span class="line">+          //! 8. 失败了 跳出循环</span><br><span class="line">+          return this.$toast(&#x27;请输入手机号或者验证码&#x27;)</span><br><span class="line">+        &#125;</span><br><span class="line">        // 5. 传入用户输入的数值 login是封装的axios登录验证方法名称</span><br><span class="line">        const ret = await login(this.mobile, this.code)</span><br><span class="line">        // 6. 进行判断 获取数据 如果获取成功 保存后端返回的 token值 不成功提示用户</span><br><span class="line">        if (ret.status === 201) &#123;</span><br><span class="line">          // 7. 再进行判断 如果用户获取到后端的token 再让其登录</span><br><span class="line">          if (ret.data.data.token &amp;&amp; ret.data.data.refresh_token) &#123;</span><br><span class="line">            // 8. 保存token值(服务器缓存)</span><br><span class="line">            // sessionStorage.setItem(&#x27;保存名称&#x27;, JSON.stringify(获取的token路径)); 保存token到服务器缓存</span><br><span class="line">            // JSON.stringif()把获取的token转换成字符串</span><br><span class="line">            sessionStorage.setItem(&#x27;mytoken&#x27;, JSON.stringify(ret.data.data))</span><br><span class="line">            this.$router.push(&#x27;/home&#x27;)</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;</span><br><span class="line">      &#125; catch (error) &#123;</span><br><span class="line">        // 登录失败时候会进入 catch 参数是错误信息</span><br><span class="line">        console.log(error)</span><br><span class="line">        // 9. 提示用户登录失败 $toast是Vant提供的模板</span><br><span class="line">        this.$toast(&#x27;登录失败&#x27;)</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure>

<h3 id="表单验证-自动挡-Vant提供"><a href="#表单验证-自动挡-Vant提供" class="headerlink" title="表单验证 自动挡(Vant提供)"></a>表单验证 自动挡(Vant提供)</h3><p><a target="_blank" rel="noopener" href="https://vant-contrib.gitee.io/vant/#/zh-CN/field">Vant field输入框样式地址</a></p>
<blockquote>
<p><code>template</code> 模板设置</p>
</blockquote>
<ul>
<li>需要创建 Vant表单 <code>&lt;van-form validate-first @submit=&#39;handleLogin&#39; @failed=&quot;onFailed&quot;&gt; &lt;/van-form&gt;</code><ul>
<li>必须把效验的数据 上传数据按钮 放在 <code>van-form</code>里面</li>
</ul>
</li>
<li>不需要设置 <strong><code>:error-message=&quot;&quot;</code></strong> 提示错误 <code>script</code> 方法可以设置</li>
<li><code>@failed=&#39;&#39;</code> 是打印错误信息 可以不设置</li>
<li><code>@submit=&#39;&#39;</code> 当验证通过时候 执行里面的函数方法 (用于绑定接口方法 验证符合条件的数据)</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    &lt;!-- 标题 --&gt;</span><br><span class="line">    &lt;van-nav-bar title=&#x27;登录&#x27; /&gt;</span><br><span class="line">    &lt;!-- 表单 --&gt;</span><br><span class="line">    &lt;van-cell-group&gt;</span><br><span class="line">      &lt;!-- validate-first 是否在某一项校验不通过时停止校验 --&gt;</span><br><span class="line">      &lt;!-- failed事件，在点击提交按钮后才会触发(可以并不用) --&gt;</span><br><span class="line">      &lt;!-- submit事件，在所有的表单验证通过后触发(绑定接口方法 验证数据) --&gt;</span><br><span class="line">      &lt;van-form validate-first @submit=&#x27;handleLogin&#x27; @failed=&quot;onFailed&quot;&gt;</span><br><span class="line">          &lt;!-- 设置:rules登录效验 声明一个对象 用于效验规则 --&gt;</span><br><span class="line">        &lt;van-field :rules=&quot;mobileRules&quot; v-model=&quot;mobile&quot; label=&quot;手机号&quot; placeholder=&quot;请输入手机号&quot; /&gt;</span><br><span class="line">        &lt;van-field :rules=&quot;codeRules&quot; v-model=&quot;code&quot; label=&quot;验证码&quot; placeholder=&quot;请输入验证码&quot;&gt;</span><br><span class="line">          &lt;!-- #button就是具名插槽的用法 --&gt;</span><br><span class="line">          &lt;template #button&gt;</span><br><span class="line">            &lt;van-button native-type=&quot;button&quot; class=&quot;p5&quot; size=&quot;mini&quot; type=&quot;primary&quot;&gt;发送验证码&lt;/van-button&gt;</span><br><span class="line">          &lt;/template&gt;</span><br><span class="line">        &lt;/van-field&gt;</span><br><span class="line">        &lt;!-- 提交按钮 --&gt;</span><br><span class="line">        &lt;div class=&quot;btn&quot;&gt;</span><br><span class="line">          &lt;van-button :loading=&#x27;isLoading&#x27; native-type=&quot;submit&quot; type=&quot;info&quot; block round&gt;登 录&lt;/van-button&gt;</span><br><span class="line">        &lt;/div&gt;</span><br><span class="line">      &lt;/van-form&gt;</span><br><span class="line">    &lt;/van-cell-group&gt;</span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br></pre></td></tr></table></figure>

<blockquote>
<p><code>script</code> 脚本设置</p>
</blockquote>
<ul>
<li>需要在 data(){}里面 设置校验即可</li>
<li>自带不满足条件不上传服务器 所有不需要设置数据上传效验</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"> data () &#123;</span><br><span class="line">   <span class="keyword">return</span> &#123;</span><br><span class="line">     <span class="comment">// 手机号</span></span><br><span class="line">     <span class="attr">mobile</span>: <span class="string">&#x27;&#x27;</span>,</span><br><span class="line">     <span class="comment">// 验证码</span></span><br><span class="line">     <span class="attr">code</span>: <span class="string">&#x27;&#x27;</span>,</span><br><span class="line"><span class="comment">// pattern:是正则表达式规则 message:是提示用户信息</span></span><br><span class="line">     <span class="attr">mobileRules</span>: [&#123; <span class="attr">pattern</span>: <span class="regexp">/^1[3-9]\d&#123;9&#125;$/</span>, <span class="attr">message</span>: <span class="string">&#x27;请输入正确手机号&#x27;</span> &#125;], </span><br><span class="line">     <span class="attr">codeRules</span>: [&#123; <span class="attr">pattern</span>: <span class="regexp">/^\d&#123;6&#125;$/</span>, <span class="attr">message</span>: <span class="string">&#x27;请输入验证码&#x27;</span> &#125;]</span><br><span class="line">   &#125;</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure>

<h3 id="表单点击事件支持"><a href="#表单点击事件支持" class="headerlink" title="表单点击事件支持"></a>表单点击事件支持</h3><p>除下列事件外，Field 默认支持 Input 标签所有的原生事件</p>
<table>
<thead>
<tr>
<th align="left">事件</th>
<th align="left">说明</th>
<th align="left">回调参数</th>
</tr>
</thead>
<tbody><tr>
<td align="left">input</td>
<td align="left">输入框内容变化时触发</td>
<td align="left"><em>value: string (当前输入的值)</em></td>
</tr>
<tr>
<td align="left">focus</td>
<td align="left">输入框获得焦点时触发</td>
<td align="left"><em>event: Event</em></td>
</tr>
<tr>
<td align="left">blur</td>
<td align="left">输入框失去焦点时触发</td>
<td align="left"><em>event: Event</em></td>
</tr>
<tr>
<td align="left">clear</td>
<td align="left">点击清除按钮时触发</td>
<td align="left"><em>event: Event</em></td>
</tr>
<tr>
<td align="left">click</td>
<td align="left">点击 Field 时触发</td>
<td align="left"><em>event: Event</em></td>
</tr>
<tr>
<td align="left">click-input <code>v2.8.1</code></td>
<td align="left">点击输入区域时触发</td>
<td align="left"><em>event: Event</em></td>
</tr>
<tr>
<td align="left">click-left-icon</td>
<td align="left">点击左侧图标时触发</td>
<td align="left"><em>event: Event</em></td>
</tr>
<tr>
<td align="left">click-right-icon</td>
<td align="left">点击右侧图标时触发</td>
<td align="left"><em>event: Event</em></td>
</tr>
</tbody></table>
<h2 id="登录按钮加载提示-Login-vue-loading"><a href="#登录按钮加载提示-Login-vue-loading" class="headerlink" title="登录按钮加载提示  Login.vue :loading"></a>登录按钮加载提示 <code> Login.vue</code> <code>:loading</code></h2><p><a target="_blank" rel="noopener" href="https://vant-contrib.gitee.io/vant/#/zh-CN/button">Vant Button 按钮</a></p>
<p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/315fhwcZ9KVmQN4.png" alt="image-20210604223154115"></p>
<blockquote>
<p>目标：实现登录按钮提示效果 (常用于电商网站购买按钮 和 登录等待验证按钮)</p>
</blockquote>
<ul>
<li>通过vant按钮的<code>:loading</code>属性实现提示效果<ul>
<li><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/h1IJviZBmW9dcnr.png" alt="image-20210604223427347"></li>
</ul>
</li>
</ul>
<ol>
<li>在<code>template</code>里面设置Vant提供的加载方法<code>:loading:&#39;对象名&#39;</code></li>
</ol>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"> &lt;!-- :loading 响应式方法 控制按钮是否加载 参数是布尔值 --&gt;</span><br><span class="line">&lt;!-- native-type=&quot;submit&quot; / button submit提交表单并且可以跳转 button提交表单但会阻止跳转 --&gt;</span><br><span class="line">     &lt;van-button :loading=&#x27;isLoading&#x27; native-type=&quot;submit&quot; @click=&quot;getLogin&quot; type=&quot;info&quot; block round&gt;登 录&lt;/van-button&gt;</span><br></pre></td></tr></table></figure>

<ol start="2">
<li>在<code>script</code>data(){}创建对象名 默认布尔值是false</li>
</ol>
<figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">  data () &#123;</span><br><span class="line">    return &#123;</span><br><span class="line">      mobile: &#x27;&#x27;,</span><br><span class="line">      code: &#x27;&#x27;,</span><br><span class="line">      //! 错误提示-手机号</span><br><span class="line">      mobileMsg: &#x27;&#x27;,</span><br><span class="line">      //! 错误提示-验证码</span><br><span class="line">      codeMsg: &#x27;&#x27;,</span><br><span class="line"><span class="addition">+      // ? 登录按钮的加载状态(布尔值 默认要设置flase 让用户能点)</span></span><br><span class="line"><span class="addition">+      isLoading: false</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br></pre></td></tr></table></figure>

<ol start="3">
<li>在接口调用方法中 调用 判断是否登录成功<ul>
<li>try{}里面设置为 true 提交数据成功后 不让其点击 <code>  this.isLoading = true</code></li>
<li>catch{} 里面重新设置为 false 登录失败 取消按钮加载 让其点击<code>this.isLoading = false</code></li>
</ul>
</li>
</ol>
<figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line">    async getLogin () &#123;</span><br><span class="line">      // 4. 用try catch 来判断 数据是否接收成功 提示用户</span><br><span class="line">      try &#123; // 给服务器发送信息</span><br><span class="line">        //! 5. 调用登录效验方法</span><br><span class="line">        this.validateMobile()</span><br><span class="line">        this.validateCode()</span><br><span class="line">        //! 6. 通过提示信息判断是否效验成功 不成功 提示用户失败 跳出判断</span><br><span class="line">        if (this.mobileMsg !== &#x27;&#x27; || this.codeMsg !== &#x27;&#x27;) &#123;</span><br><span class="line">          //! 8. 失败了 跳出循环</span><br><span class="line">          return this.$toast(&#x27;请输入手机号或者验证码&#x27;)</span><br><span class="line">        &#125;</span><br><span class="line"><span class="addition">+         // ? 登录时候进行接口调用 让其转起来 防止重复提交表单</span></span><br><span class="line"><span class="addition">+        this.isLoading = true</span></span><br><span class="line">        // 5. 传入用户输入的数值 login是封装的axios登录验证方法名称</span><br><span class="line">        const ret = await login(this.mobile, this.code)</span><br><span class="line">        // 6. 进行判断 获取数据 如果获取成功 保存后端返回的 token值 不成功提示用户</span><br><span class="line">        if (ret.status <span class="comment">=== 201) &#123;</span></span><br><span class="line">          // 7. 再进行判断 如果用户获取到后端的token 再让其登录</span><br><span class="line">          if (ret.data.data.token &amp;&amp; ret.data.data.refresh_token) &#123;</span><br><span class="line">            // 8. 保存token值(服务器缓存)</span><br><span class="line">            // sessionStorage.setItem(&#x27;保存名称&#x27;, JSON.stringify(获取的token路径)); 保存token到服务器缓存</span><br><span class="line">            // JSON.stringif()把获取的token转换成字符串</span><br><span class="line">            sessionStorage.setItem(&#x27;mytoken&#x27;, JSON.stringify(ret.data.data))</span><br><span class="line">            this.$router.push(&#x27;/home&#x27;)</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;</span><br><span class="line">      &#125; catch (error) &#123;</span><br><span class="line">        // 登录失败时候会进入 catch 参数是错误信息</span><br><span class="line">        console.log(error)</span><br><span class="line">        // 9. 提示用户登录失败 $toast是Vant提供的模板</span><br><span class="line">        this.$toast(&#x27;登录失败&#x27;)</span><br><span class="line"><span class="addition">+         // ? 登录失败的时候 还原按钮加载状态 让用户继续登录</span></span><br><span class="line"><span class="addition">+        this.isLoading = false</span></span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<h2 id="全局路由导航守卫-路由文件-index-js"><a href="#全局路由导航守卫-路由文件-index-js" class="headerlink" title="全局路由导航守卫 路由文件 index.js"></a>全局路由导航守卫 <code>路由文件 index.js</code></h2><blockquote>
<p>目标：用户没有登录页面 不让其访问 主页 等内容 让其跳转到登录页 <big>(判断token值)</big></p>
</blockquote>
<ul>
<li>Vue-router 提供方法 </li>
<li>全局导航守卫需要设置在 全局路由组件中 控制某些全局跳转</li>
<li>全局导航守卫有三个参数<ul>
<li>to 表示要跳转到哪里去</li>
<li>from 表示从哪里跳转过来的</li>
<li>next 表示具体跳转到哪里 如果不调用 无法看到组件</li>
<li><big>注意: </big>必须要设置在路由映射生效之后 导出路由之前</li>
</ul>
</li>
</ul>
<blockquote>
<p>全局导航守卫  路由文件夹<code>router</code>里面 <code>index.js</code></p>
</blockquote>
<ol>
<li>判断用户是否登录 (判断其token值) 如果没登录 转到登录页<ul>
<li>判断需要两个条件 <ul>
<li>需要判断用户是否存在 token值 不存在跳转到登录页面 <code>next(&#39;/路径&#39;)</code></li>
<li>判断是否处于登录页 如果在登录页 无需跳转<code> to.path</code>是判断是否处于某个页面</li>
</ul>
</li>
</ul>
</li>
<li>如果已经登录不管直接 <code>next()</code></li>
</ol>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 设置全局导航守卫(路由跳转到目标组件之前 先经过导航守卫进行效验)</span></span><br><span class="line"><span class="comment">// 判断其token值 如果不存在 转到登录页面 如果已经在登录页面 则判断不需要跳转</span></span><br><span class="line">router.<span class="title function_">beforeEach</span>(<span class="function">(<span class="params">to, <span class="keyword">from</span>, next</span>) =&gt;</span> &#123;</span><br><span class="line">  <span class="comment">// to 表示要跳转到哪里去</span></span><br><span class="line">  <span class="comment">// from 表示从哪里跳转过来的</span></span><br><span class="line">  <span class="comment">// next 表示具体跳转到哪里 如果不调用 无法看到组件</span></span><br><span class="line"></span><br><span class="line">  <span class="comment">// 判断用户是否已经登录</span></span><br><span class="line">  <span class="comment">// 1. 查询用户是否已经登录 把用户token值转换为字符串 (两个token 临时token 和 续费token)</span></span><br><span class="line">  <span class="keyword">const</span> userToken = <span class="title class_">JSON</span>.<span class="title function_">parse</span>(sessionStorage.<span class="title function_">getItem</span>(<span class="string">&#x27;mytoken&#x27;</span>))</span><br><span class="line">  <span class="comment">// 2. 获取字符串整合token 和 两个token的值 (两个token 临时token 和 续费token)</span></span><br><span class="line">  <span class="keyword">const</span> flag = userToken &amp;&amp; userToken.<span class="property">token</span> &amp;&amp; userToken.<span class="property">refresh_token</span><span class="comment">// 判断是否存在token值 存在返回true</span></span><br><span class="line">  <span class="comment">// 3. 进行token判断 是否存在token 和 是否处于登录页 to.path是判断是否处于某个页面</span></span><br><span class="line">  <span class="keyword">if</span> (!flag &amp;&amp; to.<span class="property">path</span> !== <span class="string">&#x27;/Login&#x27;</span>) &#123;</span><br><span class="line">    <span class="comment">// 4. 如果没登录 进入判断进行跳转</span></span><br><span class="line">    <span class="title function_">next</span>(<span class="string">&#x27;/Login&#x27;</span>)</span><br><span class="line">  &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="comment">// 5. 如果已经登录 直接next()即可</span></span><br><span class="line">    <span class="title function_">next</span>()</span><br><span class="line">  &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<blockquote>
<p>总结：</p>
<ol>
<li>前置全局导航守卫：拦截所有的路由请求</li>
<li>如果登录了，就正常跳转到组件，否则调回到登录组件</li>
</ol>
</blockquote>
<h3 id="导航守卫工作流程"><a href="#导航守卫工作流程" class="headerlink" title="导航守卫工作流程"></a>导航守卫工作流程</h3><p><img src="https://jinyanlong-1305883696.cos.ap-hongkong.myqcloud.com/n5NRQfYb9pK36rZ.png" alt="image-20210604171827880"></p>
<h2 id="调用接口获取频道数据-channel-js"><a href="#调用接口获取频道数据-channel-js" class="headerlink" title="调用接口获取频道数据 channel.js"></a>调用接口获取频道数据 <code>channel.js</code></h2><blockquote>
<p>目标：如果用户登录 获取频道列表数据，用于测试请求拦截器和token有效期</p>
</blockquote>
<ul>
<li>在<code>api文件夹 新建 channel.js</code> 单独路由配置文件下</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 获取频道列表数据，用于测试请求拦截器和token有效期</span></span><br><span class="line"><span class="comment">// 导入封装的接口组件</span></span><br><span class="line"><span class="keyword">import</span> request <span class="keyword">from</span> <span class="string">&#x27;../utils/request&#x27;</span></span><br><span class="line"><span class="comment">// ? 获取用户的频道数据(如果没有登录，返回默认的频道数据；如果登录了，就返回该用户自己的数据)</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">const</span> <span class="title function_">getAllChannels</span> = (<span class="params"></span>) =&gt; &#123;</span><br><span class="line">  <span class="comment">// ? 携带请求方式 请求地址 获取相应用户的登录频道数据(根据token判断不同用户)</span></span><br><span class="line">  <span class="keyword">return</span> <span class="title function_">request</span>(&#123;</span><br><span class="line">    <span class="attr">method</span>: <span class="string">&#x27;get&#x27;</span>,</span><br><span class="line">    <span class="attr">url</span>: <span class="string">&#x27;v1_0/user/channels&#x27;</span></span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<ul>
<li>调用接口获取频道数据<ul>
<li><code>main文件夹 main.vue</code></li>
</ul>
</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">// 文件的路径 src/views/main/index.vue</span><br><span class="line">&lt;script&gt;</span><br><span class="line">import &#123; getAllChannels &#125; from &#x27;@/api/channel.js&#x27;</span><br><span class="line">export default &#123;</span><br><span class="line">  name: &#x27;Home&#x27;,</span><br><span class="line">  created () &#123;</span><br><span class="line">    getAllChannels()</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure>

<h2 id="设置axios获取数据-create-分支-request-js"><a href="#设置axios获取数据-create-分支-request-js" class="headerlink" title="设置axios获取数据 .create 分支 request.js"></a>设置axios获取数据 .create 分支 <code>request.js</code></h2><ul>
<li><code>使用axios.create(&#123;&#125;)</code> 设置axios方法分支<ul>
<li>设置分支可以单独设置url基础地址 方便管理调用</li>
<li>单独用常量 设置url基础地址 在<code>axios.create(&#123;&#125;)</code>里面和<code>baseURL</code>属性名比对 <ul>
<li>单独常量设置地址 单独设置地址拼接</li>
</ul>
</li>
</ul>
</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 导入 axios组件</span></span><br><span class="line"><span class="keyword">import</span> axios <span class="keyword">from</span> <span class="string">&#x27;axios&#x27;</span></span><br><span class="line"><span class="comment">// 设置基准axios路径 用常量保存</span></span><br><span class="line"><span class="keyword">const</span> baseURL = <span class="string">&#x27;http://api-toutiao-web.itheima.net/app/&#x27;</span></span><br><span class="line"><span class="comment">// axios分支的方法 创建axios接口调用方法 取代单一的axios方法(方便单独设置)</span></span><br><span class="line"><span class="keyword">const</span> instance = axios.<span class="title function_">create</span>(&#123;</span><br><span class="line">  <span class="comment">// baseURL是axios属性 用来声明url基础路径(比对上面声明的常量)</span></span><br><span class="line">  <span class="attr">baseURL</span>: baseURL</span><br><span class="line">&#125;)</span><br><span class="line"><span class="comment">// 封装通用的接口调用方法</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> (options) =&gt; &#123;</span><br><span class="line">  <span class="comment">// 这里的返回值是Promise实例对象</span></span><br><span class="line">    <span class="comment">// return 返回数据 instance是声明的axios分支方法</span></span><br><span class="line">  <span class="keyword">return</span> <span class="title function_">instance</span>(&#123;</span><br><span class="line">    <span class="comment">// 设置请求方式</span></span><br><span class="line">    <span class="attr">method</span>: options.<span class="property">method</span> || <span class="string">&#x27;GET&#x27;</span>,</span><br><span class="line">    <span class="comment">// 设置请求地址</span></span><br><span class="line">    <span class="attr">url</span>: options.<span class="property">url</span>,</span><br><span class="line">    <span class="comment">// POST/PUT请求参数（请求体）</span></span><br><span class="line">    <span class="attr">data</span>: options.<span class="property">data</span>,</span><br><span class="line">    <span class="comment">// GET请求参数（自动拼接到url地址中）</span></span><br><span class="line">    <span class="attr">params</span>: options.<span class="property">params</span>,</span><br><span class="line">    <span class="comment">// 设置请求头(一般用于跨域问题 和 传输token)</span></span><br><span class="line">    <span class="attr">headers</span>: options.<span class="property">headers</span></span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h2 id="添加请求拦截器-请求头统一携带token-request-js"><a href="#添加请求拦截器-请求头统一携带token-request-js" class="headerlink" title="添加请求拦截器 请求头统一携带token request.js"></a>添加请求拦截器 请求头统一携带token <code>request.js</code></h2><blockquote>
<p>需要把数据 <code>return回去</code></p>
</blockquote>
<ul>
<li>请求拦截器的作用是 在发送请求之前 进行一些操作 <ul>
<li>在每个请求体里面加上token值 (登录后用户权限信息)</li>
</ul>
</li>
</ul>
<blockquote>
<p>发送请求前 判断是否登录(有token) 如果登录 携带请求头 发送给服务器 <code>utils文件夹 request.js</code> 路由工具文件下</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 导入 axios组件</span></span><br><span class="line"><span class="keyword">import</span> axios <span class="keyword">from</span> <span class="string">&#x27;axios&#x27;</span></span><br><span class="line"><span class="comment">// 设置基准axios路径 用常量保存</span></span><br><span class="line"><span class="keyword">const</span> baseURL = <span class="string">&#x27;http://api-toutiao-web.itheima.net/app/&#x27;</span></span><br><span class="line"><span class="comment">// axios分支的方法 创建axios接口调用方法 取代单一的axios方法(方便单独设置)</span></span><br><span class="line"><span class="keyword">const</span> instance = axios.<span class="title function_">create</span>(&#123;</span><br><span class="line">  <span class="comment">// baseURL是axios属性 用来声明url基础路径(比对上面声明的常量)</span></span><br><span class="line">  <span class="attr">baseURL</span>: baseURL</span><br><span class="line">&#125;)</span><br><span class="line"><span class="comment">// 添加一个请求拦截器 (发送数据 进行处理)</span></span><br><span class="line"><span class="comment">// 请求截拦器的作用是再请求发送前 进行一些操作 例如在每个请求体上加上token 获取登录权限后的数据</span></span><br><span class="line"><span class="comment">// config 是数据发送请求的属性</span></span><br><span class="line">instance.<span class="property">interceptors</span>.<span class="property">request</span>.<span class="title function_">use</span>(<span class="keyword">function</span> (<span class="params">config</span>) &#123;</span><br><span class="line">  <span class="comment">//! 0.发送请求前 添加响应的token值 获取相应的登录数据</span></span><br><span class="line">  <span class="comment">//! 1. 读取用户存在浏览器的token值 (需要转换成字符串)</span></span><br><span class="line">  <span class="keyword">const</span> user = <span class="title class_">JSON</span>.<span class="title function_">parse</span>(sessionStorage.<span class="title function_">getItem</span>(<span class="string">&#x27;mytoken&#x27;</span>) || <span class="literal">null</span>) <span class="comment">//! 如果没有token 赋值为null</span></span><br><span class="line">  <span class="comment">//! 2. 进行判断 如果存在token值 则添加相应的token值(三层判断) 是否存在 老token 新token</span></span><br><span class="line">  <span class="keyword">if</span> (user &amp;&amp; user.<span class="property">token</span> &amp;&amp; user.<span class="property">refresh_token</span>) &#123;</span><br><span class="line">    <span class="comment">//! 3. 如果存在token 登录成功 统一添加请求头携带其相应token(携带老token)</span></span><br><span class="line">    <span class="comment">//! config是发送的数据 headers是axios请求头Authorization是后端接口判断token的属性名</span></span><br><span class="line">    config.<span class="property">headers</span>.<span class="property">Authorization</span> = <span class="string">&#x27;Bearer &#x27;</span> + user.<span class="property">token</span> <span class="comment">// &#x27;Bearer &#x27;是后端声明的token前置</span></span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> config</span><br><span class="line">&#125;, <span class="keyword">function</span> (<span class="params">error</span>) &#123;</span><br><span class="line">  <span class="comment">// 请求如果出错了可以做一些事情</span></span><br><span class="line">  <span class="keyword">return</span> <span class="title class_">Promise</span>.<span class="title function_">reject</span>(error)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<h2 id="添加响应拦截器-统一处理axios返回数据-request-js"><a href="#添加响应拦截器-统一处理axios返回数据-request-js" class="headerlink" title="添加响应拦截器 统一处理axios返回数据 request.js"></a>添加响应拦截器 统一处理axios返回数据 <code>request.js</code></h2><blockquote>
<p>需要把数据 <code>return回去</code></p>
</blockquote>
<ul>
<li>响应拦截器的作用是数据接收响应后进行一些操作 <ul>
<li><big>续签token</big></li>
<li>判断refresh_token 是否失效 如果失效 让其重新登录</li>
<li>获取axios数据后进行加工 直接进入 data里面 <code>return response.data</code></li>
</ul>
</li>
</ul>
<blockquote>
<p>响应拦截器应用场景：处理服务器返回的数据   <code>utils文件夹 request.js</code> 路由工具文件下</p>
</blockquote>
<ul>
<li>这样在使用数据时可以少写一层data</li>
</ul>
<figure class="highlight diff"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">// 导入 axios组件</span><br><span class="line">import axios from &#x27;axios&#x27;</span><br><span class="line">// 设置基准axios路径 用常量保存</span><br><span class="line">const baseURL = &#x27;http://api-toutiao-web.itheima.net/app/&#x27;</span><br><span class="line">// axios分支的方法 创建axios接口调用方法 取代单一的axios方法(方便单独设置)</span><br><span class="line">const instance = axios.create(&#123;</span><br><span class="line">  // baseURL是axios属性 用来声明url基础路径(比对上面声明的常量)</span><br><span class="line">  baseURL: baseURL</span><br><span class="line">&#125;)</span><br><span class="line">// 添加一个响应拦截器</span><br><span class="line">instance.interceptors.response.use(function (response) &#123;</span><br><span class="line">  // 服务器返回的200范围内的状态码都会触发该函数</span><br><span class="line">  // 针对向应的数据可以做一些处理</span><br><span class="line">  console.log(&#x27;before response&#x27;)</span><br><span class="line"><span class="addition">+  // 拦截器在返回数据之前，直接获取后端的原始数据，然后再返回</span></span><br><span class="line"><span class="addition">+  return response.data</span></span><br><span class="line">&#125;, function (error) &#123;</span><br><span class="line">  // 服务器返回的200范围以外的状态码都会触发该函数</span><br><span class="line">  // 针对向应的错误信息可以做一些处理</span><br><span class="line">  return Promise.reject(error)</span><br><span class="line">&#125;)</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h2 id="响应式拦截器-续签token问题-request-js"><a href="#响应式拦截器-续签token问题-request-js" class="headerlink" title="响应式拦截器 续签token问题 request.js"></a>响应式拦截器 续签token问题 <code>request.js</code></h2><ul>
<li>token续签需要用到 axios提供的 响应式截拦器<code>.interceptors.response.use()</code></li>
<li>token续签总流程图</li>
</ul>
<p><img src="https://i.loli.net/2021/06/06/VaQ6uA7POdc8qJv.png" alt="image-20210605115451235"></p>
<ul>
<li>token分为两种<ul>
<li><code>token</code> 普通的token 用于访问需要身份验证的普通接口 获取数据 (一般有效期2小时)</li>
<li><code>refresh_token</code> 续签token 如果普通的token失效了 需要用这个续签 如果两者都失效 需要重新登陆(一般有效期为14天)</li>
</ul>
</li>
<li>token续签 前端流程总结：<ol>
<li>判断token是否失效，如果失效换取新的token（根据refresh_token）</li>
<li>把新的token覆盖到缓存中</li>
<li>重新发送请求调用刚才出错的地址</li>
<li>处理refresh_token失效的情况（失效后跳转到登录页面）</li>
</ol>
</li>
<li><big>注意: </big> token续签需要用到 使用<code>axios.create(&#123;&#125;)</code>  不影响其他功能  单独配置续签地址</li>
</ul>
<blockquote>
<p>续签token代码 <code>utils文件夹 request.js</code> 路由工具文件下  引入在 单独配置登录<code>api文件下</code>的<code>login.js</code> </p>
</blockquote>
<ul>
<li>&#x2F;&#x2F;~ 注释为 token续签过程注释</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//~ 导入 axios组件</span></span><br><span class="line"><span class="keyword">import</span> axios <span class="keyword">from</span> <span class="string">&#x27;axios&#x27;</span></span><br><span class="line"><span class="comment">//~ 导入 router组件 调用跳转方法</span></span><br><span class="line"><span class="keyword">import</span> router <span class="keyword">from</span> <span class="string">&#x27;../router/index&#x27;</span></span><br><span class="line"><span class="comment">// ~ 目标: (1) 续签token (2) 如果refresh_token失效 就认为登录过期 需要重新登录 try&#123;&#125; catch&#123;&#125;</span></span><br><span class="line"><span class="comment">// ~ 双token机制 :</span></span><br><span class="line"><span class="comment">// ~ 一个 token为获取数据token(保质期短 需要续签)</span></span><br><span class="line"><span class="comment">// ~ 一个是配合续签的token(不支持获取数据 只能续签 保质期长)</span></span><br><span class="line"><span class="comment">// ~ 1. 续签token 设置axios.create(&#123;&#125;) 设置axios分支</span></span><br><span class="line"><span class="comment">// ~ axios.create(&#123;&#125;)分支可以设置多个基础url地址</span></span><br><span class="line"><span class="comment">// ~ 2. 声明一个通用的url基础地址 用于申请token的基础路径 用常量保存</span></span><br><span class="line"><span class="keyword">const</span> baseURL = <span class="string">&#x27;http://api-toutiao-web.itheima.net/app/&#x27;</span></span><br><span class="line"><span class="comment">// ~ 3. axios分支的方法 创建axios接口调用方法 取代单一的axios方法(方便单独设置)</span></span><br><span class="line"><span class="keyword">const</span> instance = axios.<span class="title function_">create</span>(&#123;</span><br><span class="line">  <span class="comment">// ~ baseURL是axios属性 用来声明url基础路径</span></span><br><span class="line">  <span class="attr">baseURL</span>: baseURL</span><br><span class="line">&#125;)</span><br><span class="line"><span class="comment">// 封装通用的接口调用方法</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> (options) =&gt; &#123;</span><br><span class="line">  <span class="comment">// 这里的返回值是Promise实例对象</span></span><br><span class="line">  <span class="keyword">return</span> <span class="title function_">instance</span>(&#123;</span><br><span class="line">    <span class="comment">// 设置请求方式</span></span><br><span class="line">    <span class="attr">method</span>: options.<span class="property">method</span> || <span class="string">&#x27;GET&#x27;</span>,</span><br><span class="line">    <span class="comment">// 设置请求地址</span></span><br><span class="line">    <span class="attr">url</span>: options.<span class="property">url</span>,</span><br><span class="line">    <span class="comment">// POST/PUT请求参数（请求体）</span></span><br><span class="line">    <span class="attr">data</span>: options.<span class="property">data</span>,</span><br><span class="line">    <span class="comment">// GET请求参数（自动拼接到url地址中）</span></span><br><span class="line">    <span class="attr">params</span>: options.<span class="property">params</span>,</span><br><span class="line">    <span class="comment">// 设置请求头</span></span><br><span class="line">    <span class="attr">headers</span>: options.<span class="property">headers</span></span><br><span class="line">  &#125;)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 添加响应拦截器 (获取数据 进行处理)</span></span><br><span class="line"><span class="comment">// 响应截拦器是接收到数据 进行一些操作</span></span><br><span class="line"><span class="comment">// 请求结果返回后，先不直接导出，而是先对响应码等等进行处理，处理好后再导出给页面</span></span><br><span class="line"><span class="comment">// response获取的是 axios处理后的数据</span></span><br><span class="line"><span class="comment">// ?  1.常用于清除axios自带data 方便操作</span></span><br><span class="line">instance.<span class="property">interceptors</span>.<span class="property">response</span>.<span class="title function_">use</span>(<span class="keyword">function</span> (<span class="params">response</span>) &#123; <span class="comment">// 获取数据成功时候</span></span><br><span class="line">  <span class="comment">// 当获取数据成功时候 直接进入axios里的data</span></span><br><span class="line">  <span class="keyword">return</span> response.<span class="property">data</span></span><br><span class="line">&#125;, <span class="keyword">async</span> <span class="keyword">function</span> (<span class="params">error</span>) &#123; <span class="comment">// ~ 4. 通常要用async函数还获取新token值(省去then步骤)</span></span><br><span class="line">  <span class="comment">// ~ 开始进行续签token</span></span><br><span class="line">  <span class="comment">// ~ 5. 判断token是否失效 错误参数是error</span></span><br><span class="line">  <span class="comment">// ~ error里面参数response里面status是服务器返回值401(401无权限访问)</span></span><br><span class="line">  <span class="keyword">if</span> (error.<span class="property">response</span>.<span class="property">status</span> === <span class="number">401</span>) &#123;</span><br><span class="line">    <span class="comment">// ~ 6. 如果refresh_token 是有效的 续签token</span></span><br><span class="line">    <span class="keyword">try</span> &#123;</span><br><span class="line">      <span class="comment">// ~ 7. 如果token失效了 申请一个新的token(根据 refresh_token)</span></span><br><span class="line">    <span class="comment">// ~ 8. 调用浏览器储存的token (主要用 refresh_token)</span></span><br><span class="line">      <span class="keyword">const</span> user = <span class="title class_">JSON</span>.<span class="title function_">parse</span>(sessionStorage.<span class="title function_">getItem</span>(<span class="string">&#x27;mytoken&#x27;</span>) || <span class="literal">null</span>)</span><br><span class="line">      <span class="comment">// ~ 9. 调用接口 用refresh_token 跟服务器比对 如果成功 续签token</span></span><br><span class="line">      <span class="keyword">const</span> info = <span class="keyword">await</span> <span class="title function_">axios</span>(&#123;</span><br><span class="line">      <span class="comment">// ~ 10. 设置续签token的请求方式 (put请求方式 替换修改的所有数据)</span></span><br><span class="line">        <span class="attr">method</span>: <span class="string">&#x27;put&#x27;</span>,</span><br><span class="line">        <span class="comment">// ~ 11. 设置续签token的地址 基础url+token地址</span></span><br><span class="line">        <span class="attr">url</span>: baseURL + <span class="string">&#x27;v1_0/authorizations&#x27;</span>,</span><br><span class="line">        <span class="attr">headers</span>: &#123;</span><br><span class="line">        <span class="comment">// ~ 12. 设置请求头 携带refresh_token 和服务器进行比对 如果成功 续签新token</span></span><br><span class="line">          <span class="title class_">Authorization</span>: <span class="string">&#x27;Bearer &#x27;</span> + user.<span class="property">refresh_token</span></span><br><span class="line">        &#125;</span><br><span class="line">      &#125;)</span><br><span class="line">      <span class="comment">// ~ 13. 获取最新的token数据 覆盖user里面的原先的失效token (在data.data里面的token)</span></span><br><span class="line">      user.<span class="property">token</span> = info.<span class="property">data</span>.<span class="property">data</span>.<span class="property">token</span></span><br><span class="line">      <span class="comment">// ~ 14. 在浏览器中缓存中保存新获取的token值</span></span><br><span class="line">      sessionStorage.<span class="title function_">setItem</span>(<span class="string">&#x27;mytoken&#x27;</span>, <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(user))</span><br><span class="line">      <span class="comment">// ~ 15. 重新调用刚才接口 用新token访问服务器 实现续签成功</span></span><br><span class="line">      <span class="comment">// ~ error是返回错误值的参数 config是错误参数中的属性名 里面包含url地址 请求方式等 相当于重新请求服务器</span></span><br><span class="line">      <span class="keyword">return</span> <span class="title function_">instance</span>(error.<span class="property">config</span>) <span class="comment">// ~ return 如果数据正确就返回去 不打印下面打印信息</span></span><br><span class="line">      <span class="comment">// ~ 16. 如果refresh_token失效 让其重新登录 账号获取新的refresh_token (状态码403)</span></span><br><span class="line">    &#125; <span class="keyword">catch</span> (error) &#123;</span><br><span class="line">      <span class="comment">// ~ 17. refresh_token失效 让其返回登录页面(需要调用router 组件 利用router方法跳转)</span></span><br><span class="line">      <span class="keyword">return</span> router.<span class="title function_">push</span>(<span class="string">&#x27;/login&#x27;</span>) <span class="comment">// ~ 让其跳转到首页 return返回数据 不让其执行下面错误提示</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> <span class="title class_">Promise</span>.<span class="title function_">reject</span>(error)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>


        </div>
        
            <div class="kratos-copyright text-center clearfix">
                <h5>本作品采用 <a rel="license nofollow" target="_blank" href="https://creativecommons.org/licenses/by-sa/4.0/">知识共享署名-相同方式共享 4.0 国际许可协议</a> 进行许可</h5>
            </div>
        
        <footer class="kratos-entry-footer clearfix">
            
                <div class="post-like-donate text-center clearfix" id="post-like-donate">
                
                
                    <a class="share" href="javascript:;"><i class="fa fa-share-alt"></i> 分享</a>
                    <div class="share-wrap" style="display: none;">
    <div class="share-group">
        <a href="javascript:;" class="share-plain qq" onclick="share('qq');" rel="nofollow">
            <div class="icon-wrap">
                <i class="fa fa-qq"></i>
            </div>
        </a>
        <a href="javascript:;" class="share-plain qzone" onclick="share('qzone');" rel="nofollow">
            <div class="icon-wrap">
                <i class="fa fa-star"></i>
            </div>
        </a>
        <a href="javascript:;" class="share-plain weixin pop style-plain" rel="nofollow">
            <div class="icon-wrap">
                <i class="fa fa-weixin"></i>
            </div>
            <div class="share-int">
                <div class="qrcode" id="wechat-qr"></div>
                <p>打开微信“扫一扫”，打开网页后点击屏幕右上角分享按钮</p>
            </div>
        </a>
        <a href="javascript:;" class="share-plain weibo" onclick="share('weibo');" rel="nofollow">
            <div class="icon-wrap">
                <i class="fa fa-weibo"></i>
            </div>
        </a>
        <a href="javascript:;" class="share-plain facebook style-plain" onclick="share('facebook');" rel="nofollow">
            <div class="icon-wrap">
                <i class="fa fa-facebook"></i>
            </div>
        </a>
        <a href="javascript:;" class="share-plain twitter style-plain" onclick="share('twitter');" rel="nofollow">
            <div class="icon-wrap">
                <i class="fa fa-twitter"></i>
            </div>
        </a>
    </div>
    <script type="text/javascript">
        $(()=>{
            new QRCode("wechat-qr", {
                text: "https://cuishikang.gitee.io/2021/06/04/Vue_Mobile_Projects/4_login/",
                width: 150,
                height: 150,
                correctLevel : QRCode.CorrectLevel.H
            });
        });
        function share(dest) {
            const qqBase        = "https://connect.qq.com/widget/shareqq/index.html?";
            const weiboBase     = "https://service.weibo.com/share/share.php?";
            const qzoneBase     = "https://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?";
            const facebookBase  = "https://www.facebook.com/sharer/sharer.php?";
            const twitterBase   = "https://twitter.com/intent/tweet?";
            const hostUrl       = "https://cuishikang.gitee.io/2021/06/04/Vue_Mobile_Projects/4_login/";
            const title         = "「3. Vue移动端 基本登录功能」";
            const excerpt       = `::: tip 介绍
Vant插件的登录功能(基本功能 访问数据 访问权限功能 token续签):::`;
            let _URL;
            switch (dest) {
                case "qq"       : _URL = qqBase+"url="+hostUrl+"&title="+title+"&desc=&summary="+excerpt+"&site=cxpy";     break;
                case "weibo"    : _URL = weiboBase+"url="+hostUrl+"&title="+title+excerpt;                                 break;
                case "qzone"    : _URL = qzoneBase+"url="+hostUrl+"&title="+title+"&desc=&summary="+excerpt+"&site=cxpy";  break;
                case "facebook" : _URL = facebookBase+"u="+hostUrl;                                                        break;
                case "twitter"  : _URL = twitterBase+"text="+title+excerpt+"&url="+hostUrl;                                break;
            }
            window.open(_URL);
        };
    </script>
</div>
                
                </div>
            
            <div class="footer-tag clearfix">
                <div class="pull-left">
                <i class="fa fa-tags"></i>
                    <a class="tag-none-link" href="/tags/Vant/" rel="tag">Vant</a>, <a class="tag-none-link" href="/tags/Vue/" rel="tag">Vue</a>, <a class="tag-none-link" href="/tags/Vue%E7%A7%BB%E5%8A%A8%E7%AB%AF/" rel="tag">Vue移动端</a>
                </div>
                <div class="pull-date">
                <span>最后编辑：2022-02-19</span>
                </div>
            </div>
        </footer>
    </div>
    
        <nav class="navigation post-navigation clearfix" role="navigation">
            
            <div class="nav-previous clearfix">
                <a title=" 2. Vue移动端 项目架构" href="/2021/06/03/Vue_Mobile_Projects/3_Frame/">&lt; 上一篇</a>
            </div>
            
            
            <div class="nav-next clearfix">
                <a title=" 4. Vue移动端 频道关联文章列表" href="/2021/06/08/Vue_Mobile_Projects/5_Home/">下一篇 &gt;</a>
            </div>
            
        </nav>
    
    
</article>

        

            </section>

        

                
            

<section id="kratos-widget-area" class="col-md-4 hidden-xs hidden-sm">
    <!-- 文章和页面根据splitter来分割，没有的话就从头开始设置为sticky -->
    
    
                <aside id="krw-about" class="widget widget-kratos-about clearfix">
    <div class="photo-background"></div>
    <div class="photo-wrapper clearfix">
        <div class="photo-wrapper-tip text-center">
            <img class="about-photo" src="https://gitee.com/cuishikang/tmp/raw/master/img/20220220194141.png" />
        </div>
    </div>
    <div class="textwidget">
        <p class="text-center"></p>
    </div>
    <div class="site-meta">
        <a class="meta-item" href="/archives/">
            <span class="title">
                文章
            </span>
            <span class="count">
                91
            </span>
        </a>
        <a class="meta-item" href="/categories/">
            <span class="title">
                分类
            </span>
            <span class="count">
                13
            </span>
        </a>
        <a class="meta-item" href="/tags/">
            <span class="title">
                标签
            </span>
            <span class="count">
                33
            </span>
        </a>
    </div>
</aside>
            
                    <div class="sticky-area">
                
                
  <aside id="krw-categories" class="widget widget-kratos-categories clearfix">
    <h4 class="widget-title"><i class="fa fa-folder"></i>分类目录</h4>
      <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/categories/Css/">Css</a><span class="category-list-count">4</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/JavaScript/">JavaScript</a><span class="category-list-count">15</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/RABC/">RABC</a><span class="category-list-count">2</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Vscode/">Vscode</a><span class="category-list-count">1</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Vue/">Vue</a><span class="category-list-count">13</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Vue3/">Vue3</a><span class="category-list-count">25</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/Vue%E7%A7%BB%E5%8A%A8%E5%A4%B4%E6%9D%A1%E9%A1%B9%E7%9B%AE/">Vue移动头条项目</a><span class="category-list-count">10</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/animation/">animation</a><span class="category-list-count">4</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/axios/">axios</a><span class="category-list-count">7</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/other/">other</a><span class="category-list-count">2</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/uniapp/">uniapp</a><span class="category-list-count">3</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/vue-element-admin/">vue-element-admin</a><span class="category-list-count">2</span></li><li class="category-list-item"><a class="category-list-link" href="/categories/%E5%B0%8F%E7%A8%8B%E5%BA%8F/">小程序</a><span class="category-list-count">2</span></li></ul>
  </aside>


            
                
  <aside id="krw-tags" class="widget widget-kratos-tags clearfix">
    <h4 class="widget-title"><i class="fa fa-tags"></i>标签聚合</h4>
      <div class="tag-clouds">
        <a href="/tags/Css/" style="font-size: 0.66em;">Css</a> <a href="/tags/H5Video/" style="font-size: 0.6em;">H5Video</a> <a href="/tags/JavaScript/" style="font-size: 0.74em;">JavaScript</a> <a href="/tags/My-project/" style="font-size: 0.6em;">My project</a> <a href="/tags/QQ/" style="font-size: 0.6em;">QQ</a> <a href="/tags/RABC/" style="font-size: 0.6em;">RABC</a> <a href="/tags/Vant/" style="font-size: 0.71em;">Vant</a> <a href="/tags/VeeValidate/" style="font-size: 0.6em;">VeeValidate</a> <a href="/tags/Vscode/" style="font-size: 0.6em;">Vscode</a> <a href="/tags/Vue/" style="font-size: 0.8em;">Vue</a> <a href="/tags/Vue-Router/" style="font-size: 0.6em;">Vue Router</a> <a href="/tags/Vue3/" style="font-size: 0.77em;">Vue3</a> <a href="/tags/Vuex/" style="font-size: 0.6em;">Vuex</a> <a href="/tags/Vue%E7%A7%BB%E5%8A%A8%E7%AB%AF/" style="font-size: 0.74em;">Vue移动端</a> <a href="/tags/Windows/" style="font-size: 0.6em;">Windows</a> <a href="/tags/animation/" style="font-size: 0.63em;">animation</a> <a href="/tags/axios/" style="font-size: 0.69em;">axios</a> <a href="/tags/echarts/" style="font-size: 0.6em;">echarts</a>
      </div>
  </aside>

            
                
  <aside id="krw-posts" class="widget widget-kratos-posts">
  <h4 class="widget-title"><i class="fa fa-file"></i>最新文章</h4>
  <div class="tab-content">
      <ul class="list-group">
        
        
          
          
            <a class="list-group-item" href="/2111/02/19/JavaScript/5_algorithm_tree/"><i class="fa  fa-book"></i> JavaScript树形数据转换算法</a>
            
          
        
          
          
            <a class="list-group-item" href="/2099/01/27/Vue3/1.1.1_Vue_study/"><i class="fa  fa-book"></i> Vue3 学习手册(博客版)</a>
            
          
        
          
          
            <a class="list-group-item" href="/2022/02/28/JavaScript/0.2_scroll/"><i class="fa  fa-book"></i> JS 滚动到指定位置和回到顶部</a>
            
          
        
          
          
            <a class="list-group-item" href="/2022/02/23/Vue/5_Vue_nextTick/"><i class="fa  fa-book"></i> 理解$nextTick</a>
            
          
        
          
          
            <a class="list-group-item" href="/2022/02/20/hello-world/"><i class="fa  fa-book"></i> Hello World</a>
            
          
        
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
          
            
      </ul>
  </div>
  </aside>

            
    </div>
</section>
        
        </div>
    </div>
</div>
<footer>
    <div id="footer"  class="ap-lrc"  >
        <div class="container">
            <div class="row">
                <div class="col-md-6 col-md-offset-3 footer-list text-center">
                    <ul class="kratos-social-icons">
                        
                        
                        <li><a target="_blank" rel="nofollow" href="https://t.me/CandyUnion"><i class="fa fa-telegram"></i></a></li>
                        
                        
                        
                        <li><a target="_blank" rel="me" href="https://nya.one/@Candinya"><i class="fa fa fa-share-alt-square"></i></a></li>
                        <li><a target="_blank" rel="nofollow" href="https://github.com/Candinya"><i class="fa fa-github"></i></a></li>
                        
                    </ul>
                    <ul class="kratos-copyright">
                        <div>
                            <li>&copy; 2022 小崔的博客 版权所有.</li>
                            <li>本站已运行<span id="span_dt">Loading...</span></li>
                        </div>
                        <div>
                            <li>Theme <a href="https://github.com/Candinya/Kratos-Rebirth" target="_blank">Kratos:Rebirth</a></li>
                            <li>Site built with&nbsp;<i class="fa fa-heart throb" style="color:#d43f57"></i>&nbsp;by cuishikang.</li>
                        </div>
                        <div>
                            <li>Powered by <a href="https://hexo.io" target="_blank" rel="nofollow">Hexo</a></li>
                            <li>Hosted on <a href="https://github.io" target="_blank">Github Pages</a></li>
                        </div>
                        <div>
                            
                            
                        </div>
                    </ul>
                </div>
            </div>
        </div>
        <div class="kr-tool text-center">
            <div class="tool">
                
                    <div class="box search-box">
                        <a href="/search/">
                            <span class="fa fa-search"></span>
                        </a>
                    </div>
                
                
                    <div class="box theme-box" id="darkmode-switch">
                        <span class="fa fa-adjust"></span>
                    </div>
                
                
            </div>
            <div class="box gotop-box">
                <span class="fa fa-chevron-up"></span>
            </div>
        </div>
    </div>
</footer>
</div>
</div>

        <script defer src="https://unpkg.com/bootstrap@3.3.4/dist/js/bootstrap.min.js"></script>
<script defer src="https://unpkg.com/nprogress@0.2.0/nprogress.js"></script>
<script>
    if (!window.kr) {
        window.kr = {};
    }
    window.kr.notMobile = (!(navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)));
    window.kr.siteRoot = "/";
</script>


    <script async src="/js/candy.min.js"></script>



    <script defer src="https://unpkg.com/aplayer@1.10.1/dist/APlayer.min.js"></script>
    
    <script defer src="https://unpkg.com/meting@2/dist/Meting.min.js"></script>
    <meting-js
        server="netease"
        type="song"
        id="1375305989"
        order="random"
        fixed="true"
    >
    </meting-js>



    <script defer src="https://unpkg.com/@fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js"></script>

<script defer src="https://unpkg.com/clipboard@2.0.6/dist/clipboard.min.js"></script>
<script defer src="/js/kratosr.min.js"></script>
<script defer src="/js/pjax.min.js"></script>


    <script defer src="/js/kr-dark.min.js"></script>



<!-- Extra support for third-party plguins  -->


    </body>
</html>